package cn.dduan.fool.design.pattern.structure.agent;

/**
 * 代理模式
 * <p>
 * 优点：
 * 1、用于协调与连接调用者(即客户端)和被调用者(即目标对象)
 * 2、在一定程度上降低了系统的耦合度，同时也保护了目标对象
 * <p>
 * 缺点：
 * 1、调用者与被调用者之间增加了代理对象，造成处理速度变慢
 * <p>
 * 代理模式与装饰器模式的区别：
 * 1、装饰器模式关注于在对象上动态添加新行为，而代理模式虽然也可以增加新的行为，但关注于控制对象的访问
 * 2、装饰器模式执行主体是原类；代理模式是代理原类进行操作，执行主体是代理类
 * 3、代理模式的代理和真实对象之间的对象通常在编译时就已经确定了，而装饰者能够在运行时递归地被构造
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
public class AgentPattern {
    public static void main(String[] args) {
        // 目标对象
        BeautifulGirl mm = new BeautifulGirl("漂亮小姐姐。。。");
        // 中间人-目标对象闺蜜
        HerChum chum = new HerChum(mm);
        // 目标对象闺蜜传达我的心意
        chum.giveBook();
        chum.giveChocolate();
        chum.giveFlowers();
    }
}

/**
 * RealSubject：真实对象（漂亮美女）
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class BeautifulGirl {
    String name;

    public BeautifulGirl(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

/**
 * Subject：抽象角色（申明了调用者和被调用者的共同接口）
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
interface GiveGift {
    /**
     * 送花
     */
    void giveFlowers();

    /**
     * 送巧克力
     */
    void giveChocolate();

    /**
     * 送书
     */
    void giveBook();
}

/**
 * 我的心意
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class You implements GiveGift {
    /**
     * 美女
     */
    private BeautifulGirl mm;

    public You(BeautifulGirl mm) {
        this.mm = mm;
    }

    @Override
    public void giveBook() {
        System.out.println(mm.getName() + ",送你一本书....");
    }

    @Override
    public void giveChocolate() {
        System.out.println(mm.getName() + ",送你一盒巧克力....");
    }

    @Override
    public void giveFlowers() {
        System.out.println(mm.getName() + ",送你一束花....");
    }
}

/**
 * 代理角色（实现接口）｜ 她闺蜜
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class HerChum implements GiveGift {

    private You you;

    public HerChum(BeautifulGirl mm) {
        you = new You(mm);
    }

    @Override
    public void giveBook() {
        you.giveBook();
    }

    @Override
    public void giveChocolate() {
        you.giveChocolate();
    }

    @Override
    public void giveFlowers() {
        you.giveFlowers();
    }
}